#include "head.h"

// 重定向 print输出 输出到执行文件 .csv
int re_print_csv() {
    int fd;
    char buff[100] = __FILE__;
    buff[strlen(buff) - 2] = '\0';
    strcat(buff, ".csv");
    fd = open(buff, O_WRONLY | O_CREAT | O_TRUNC, 0666);
    sprintf(buff, "%s", __FILE__);
    dup2(fd, 1);
}

//  -lpthread
typedef struct {
    int acceptfd;
    struct sockaddr_in clientaddr;
} msg_t_pthread;

// operae 1-登录  2-查询单次  3-退出 4-注册
typedef struct msg {
    int operae;
    char user_name[100];
    char passwd[100];
    int log_fla;
    char key_1[100];
    char msg_masse[500];
    char user_name_reg[100];
    char passwd_reg[100];
    int reg_fla;
} msg_t;

static int callback(void *NotUsed, int argc, char **argv, char **azColName) {
    int i;
    for (i = 0; i < argc; i++) {
        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    }
    printf("\n");
    return 0;
}

int log_in(
        char *name_text_log, char *passwd,
        int log_stat, char *name_text, char *msg_masse_main) {
    if (log_stat == 1) {
        printf("您已经登录无需重复登录\n");
        return -1;
    }
    sqlite3 *db;
    int rc;
    char *sql, **dbResult, *errMsg;
    char buff[100] = {0};
    int nRow = 0, nColumn = 0;
    /* Open database */
    rc = sqlite3_open("/mnt/hgfs/gongxiang/c_1/test.db", &db);
    if (rc) {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        exit(0);
    }

    sprintf(buff, "select  passwd from  user_reg where  name_text='%s' ", name_text_log);

    sql = buff;

    sqlite3_get_table(db, sql, &dbResult, &nRow, &nColumn, &errMsg);
    if (nRow == 0) {
        printf("用户名错误 ::%s  没有这个用户...\n", name_text_log);
        strcpy(msg_masse_main, "用户名错误  没有这个用户");
        sqlite3_close(db);
        return -1;
    }
    int res = strcmp(dbResult[1], passwd);
    if (res == 0) {
        strcpy(name_text, name_text_log);
        log_stat = 1;
        sqlite3_close(db);
        printf("log_in success...\n");
        strcpy(msg_masse_main, "log_in success");
        return 0;
    } else {
        printf("passwd error...\n");
        strcpy(msg_masse_main, "passwd error");
        sqlite3_close(db);
        return -1;
    }
}

int insert_his(char *name_text, char *key_1) {
    sqlite3 *db;
    char *zErrMsg = 0;
    int rc;
    char *sql;
    char buff[100] = {0};

    /* Open database */
    rc = sqlite3_open("/mnt/hgfs/gongxiang/c_1/test.db", &db);
    if (rc) {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        exit(0);
    }
    sprintf(buff, "INSERT INTO user_did_his (name_text,key_1) VALUES ('%s','%s'); ", name_text, key_1);
    sql = buff;
    rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "username  register SQL error: \n");
        sqlite3_free(zErrMsg);
        sqlite3_close(db);
        return -1;
    } else {
        sqlite3_close(db);
        return 0;
    }
}

int do_serch(char *user_name, char *key_1, char *msg_masse_main) {
    sqlite3 *db;
    int rc;
    char *sql, **dbResult, *errMsg, *buff_p, *buff_p_1;
    char buff[100] = {0};
    int nRow = 0, nColumn = 0;
    /* Open database */
    rc = sqlite3_open("/mnt/hgfs/gongxiang/c_1/test.db", &db);
    if (rc) {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        exit(0);
    }

    sprintf(buff, "select  trans from  dict_1 where  key_='%s'", key_1);
    sql = buff;
    sqlite3_get_table(db, sql, &dbResult, &nRow, &nColumn, &errMsg);
    if (nRow == 0) {
        printf("单词 ::%s  没有这个单词...\n", key_1);
        sprintf(msg_masse_main, "单词 ::%s  没有这个单词...\n", key_1);
        sqlite3_close(db);
        return -1;
    }
    memset(buff, 0, sizeof(buff));
    //遍历结果 将开始的空格去掉
    for (int i = 0; i < strlen(dbResult[1]); i++) {
        if (dbResult[1][i] == 32) {}
        else {
            buff_p = &dbResult[1][i];
            break;
        }
    }
    insert_his(user_name, key_1);
    printf("%s---%s", key_1, buff_p);
    sprintf(msg_masse_main, "%s---%s", key_1, buff_p);
    return 0;
}

int reg_ins_sql(char *name, char *passwd, char *msg_masse_main) {
    sqlite3 *db;
    char *zErrMsg = 0;
    int rc;
    char *sql;
    char buff[100] = {0};

    /* Open database */
    rc = sqlite3_open("/mnt/hgfs/gongxiang/c_1/test.db", &db);
    if (rc) {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        exit(0);
    }
    // "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) "
    // "VALUES (5, 'Paul', 32, 'California', 20000.00 ); "
    sprintf(buff, "INSERT INTO user_reg (name_text,passwd) VALUES ('%s','%s'); ", name, passwd);
    sql = buff;
    rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);

    if (rc != SQLITE_OK) {
        fprintf(stderr, "username %s register SQL error: %s\n", name, zErrMsg);
        sprintf(msg_masse_main, "username %s register SQL error: %s\n", name, zErrMsg);
        sqlite3_free(zErrMsg);
        sqlite3_close(db);
        return -1;
    } else {
        fprintf(stdout, "user ::%s register success\n", name);
        sprintf(msg_masse_main, "user ::%s register success\n", name);
        sqlite3_close(db);
        return 0;
    }
}

int select_hsi(char *name_text, char *msg_masse_main) {
    sqlite3 *db;
    int rc;
    char *sql, **dbResult, *errMsg, *buff_p, *buff_p_1;
    char buff[100] = {0};
    int nRow = 0, nColumn = 0;
    /* Open database */
    rc = sqlite3_open("/mnt/hgfs/gongxiang/c_1/test.db", &db);
    if (rc) {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        exit(0);
    }
    sprintf(buff, "select  key_1 from  user_did_his where  name_text='%s'", name_text);
    sql = buff;
    sqlite3_get_table(db, sql, &dbResult, &nRow, &nColumn, &errMsg);
    if (nRow == 0) {
        printf("用户::%s  没有这个查询...\n", name_text);
        sprintf(msg_masse_main, "用户::%s  没有这个查询...\n", name_text);
        sqlite3_close(db);
        return -1;
    }
    char msg_temp[100] = {0};
    // printf("用户::%s 共查询了 %d 次\n", name_text, nRow);
    sprintf(msg_masse_main, "用户::%s 共查询了 %d 次\n", name_text, nRow);
    for (int i = 1; i <= nRow; i++) {
        memset(msg_temp, 0, 100);
        for (int j = 0; j < nColumn; j++) {
            // printf("%-5s\t", dbResult[i * nColumn + j]);
            sprintf(msg_temp, "%-5s\t", dbResult[i * nColumn + j]);
        }
        if (i % 5 == 0) {
            strcat(msg_temp, "\n");
        }
        strcat(msg_masse_main, msg_temp);
    }
    // printf("用户::%s 共查询了 %d 次\n", name_text, nRow);
    // user_did_his
    return 0;
}

void *deal_read_write(void *arg) {
    int quest_i = 0;
    char msg_masse_main[500] = {0};
    msg_t_pthread msg = *(msg_t_pthread *) arg;
    int acceptfd = msg.acceptfd;
    msg_t msg_get_user;
    for (int i = 0; i < 100; i++) {
        //阻塞等待 读取用户端发送信息
        memset(&msg_get_user, 0, sizeof(msg_t));
        read(acceptfd, &msg_get_user, sizeof(msg_t));
        printf("|user_name[%s]operae[%d]log_fla[%d]key_1[%s]passwd[%s],\n", msg_get_user.user_name, msg_get_user.operae,
               msg_get_user.log_fla, msg_get_user.key_1,
               msg_get_user.passwd);
        printf("%s:%d,\n", inet_ntoa(msg.clientaddr.sin_addr), ntohs(msg.clientaddr.sin_port));
        // 各种操作的逻辑
        quest_i = msg_get_user.operae;
        printf("%d,\n", quest_i);
        //登录
        if (quest_i == 1) {
            printf("登录,\n");
            memset(msg_masse_main, 0, 500);
            if (log_in(msg_get_user.user_name, msg_get_user.passwd, msg_get_user.log_fla, msg_get_user.user_name,
                       msg_masse_main) == 0) {
                msg_get_user.log_fla = 1;
            };
            strcpy(msg_get_user.msg_masse, msg_masse_main);
            write(acceptfd, &msg_get_user, sizeof(msg_t));
        }
        //查询
        if (quest_i == 2) {
            printf("查询,");
            do_serch(msg_get_user.user_name, msg_get_user.key_1, msg_masse_main);
            strcpy(msg_get_user.msg_masse, msg_masse_main);
            write(acceptfd, &msg_get_user, sizeof(msg_t));
        }
        //注册
        if (quest_i == 4) {
            printf("注册,");
            msg_get_user.reg_fla = reg_ins_sql(msg_get_user.user_name_reg, msg_get_user.passwd_reg, msg_masse_main);
            strcpy(msg_get_user.msg_masse, msg_masse_main);
            write(acceptfd, &msg_get_user, sizeof(msg_t));
        }
        //历史
        if (quest_i == 5) {
            printf("历史,");
            select_hsi(msg_get_user.user_name, msg_masse_main);
            strcpy(msg_get_user.msg_masse, msg_masse_main);
            write(acceptfd, &msg_get_user, sizeof(msg_t));
        }
        // if (strlen(&msg_1) == 0) { printf("接收信息len ==0 用户端关闭连接\n");break; }
        if (quest_i == 0) {}
        else {
            printf("服务端经过操作返回数据为::user_name[%s]operae [%d]log_fla [%d]key_1[%s]passwd[%s] ,%s",
                   msg_get_user.user_name, msg_get_user.operae,
                   msg_get_user.log_fla, msg_get_user.key_1,
                   msg_get_user.passwd, msg_get_user.msg_masse);
        }
    }
    close(msg.acceptfd);
    pthread_exit(NULL);
}

int main(int argc, const char *argv[]) {
    re_print_csv();
    //1.创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (-1 == sockfd) {
        ERRLOG("socket error");
    }

    //2.填充服务器网络信息结构体
    struct sockaddr_in serveraddr;
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(8888);
    serveraddr.sin_addr.s_addr = inet_addr("192.168.250.100");
    socklen_t serveraddr_len = sizeof(serveraddr);

    //3.将套接字与服务器的网络信息结构体绑定
    if (-1 == bind(sockfd, (struct sockaddr *) &serveraddr, serveraddr_len)) {
        ERRLOG("bind error");
    }

    //4.将套接字设置成被动监听状态
    if (-1 == listen(sockfd, 5)) {
        ERRLOG("listen error");
    }
    // sleep(10);
    // 定义结构体保存客户端信息
    // pthread代码
    struct sockaddr_in clientaddr;
    memset(&clientaddr, 0, sizeof(clientaddr));
    socklen_t clientaddr_len = sizeof(clientaddr);

    //5.阻塞等待客户端连接
    int acceptfd = 0;
    pthread_t tid = 0;
    msg_t_pthread msg;
    int ret = 0;
    while (1) {
        if (-1 == (acceptfd = accept(sockfd, (struct sockaddr *) &clientaddr, &clientaddr_len))) {
            ERRLOG("accept error");
        }
        msg.acceptfd = acceptfd;
        msg.clientaddr = clientaddr;
        //创建子线程 专门用于和新连接的客户端通信
        if (0 != (ret = pthread_create(&tid, NULL, deal_read_write, (void *) &msg))) {
            printf("prhread_create error, errcode = [%d], errstr = [%s]\n", ret, strerror(ret));
            exit(-1);
        }
        //设置线程分离属性 让操作系统回收线程资源
        if (0 != (ret = pthread_detach(tid))) {
            printf("pthread_detach error, errcode = [%d], errstr = [%s]\n", ret, strerror(ret));
            exit(-1);
        }
    }
    close(sockfd);

    return 0;
}